package cn.wygandwdn.core.failover.impl;

import cn.wygandwdn.common.enumeration.ErrorType;
import cn.wygandwdn.common.exception.RpcException;
import cn.wygandwdn.common.message.RpcRequest;
import cn.wygandwdn.core.config.Config;
import cn.wygandwdn.core.failover.FailoverRetry;
import cn.wygandwdn.core.transport.client.RpcClient;
import io.netty.util.concurrent.Promise;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @description:
 * @author: WYG
 * @time: 2021/11/1 21:30
 */

public class FailoverRetryImpl implements FailoverRetry {

    /**
     * 超时时间
     */
    private final int timeout = Config.getTimeout();
    /**
     * 超时重试次数
     */
    private final int retries = Config.getRetry();


    @Override
    public Object timeoutRetry(RpcClient client, Promise<Object> promise, RpcRequest request) throws ExecutionException, InterruptedException {
        if (promise.isSuccess()) {
            return promise.get();
        }
        for (int i = 0; i < retries; i++) {
            Promise<Object> retry = client.sendRequest(request);
            retry.await(timeout);
            if (retry.isSuccess()) {
                return retry.get();
            } else {
                if (retry.cause() != null) {
                    throw new RuntimeException(retry.cause());
                }
            }
        }

        throw new RpcException(ErrorType.REQUEST_TIMEOUT);
    }
}
